--[[
    单位模块

    雪月灬雪歌

    ---@author:  2022-02-18 04:03:34
]]

local CreateUnit = cj.CreateUnit
local RemoveUnit = cj.RemoveUnit
local GetUnitX = cj.GetUnitX
local GetUnitY = cj.GetUnitY
local SetUnitX = cj.SetUnitX
local SetUnitY = cj.SetUnitY
local SetUnitOwner = cj.SetUnitOwner

---@class unit
---@field abilitys ability[]
---@field player player
---@field id string
---@field handle handle
---@field hid int
local cUnit = {
    type = 'class',
    class = 'unit',
    __mode = 'k',

}
cUnit.__index = cUnit

---@class mUnit
---@field public on_death fun(params:table) 单位死亡回调 params => killer,death
---@field public cUnit unit
unit = {
    type = 'module',
    module = 'unit',
    __mode = 'k',

    _h2u = {},

    cUnit = cUnit
}
unit.__index = unit



---@def module.unit.init
xconst.unit = {}

local unit_n2i = function (name)
    return xslk.unit:n2i(name)
end

local unit_n2i_like = function (name)
    return xslk.unit:n2i_like(name)
end

local f_at = {
    ['@'] = unit_n2i,
    ['*'] = unit_n2i_like,
}

local iid_cache = { }
local sid_cache = { }
local function convert_id ( param )
    local at = f_at [ param:sub(1,1) ]
    if at then
        sid_cache[ param ] = at( param:sub(2) ) or 'hpea'
    else
        sid_cache[ param ] =  param
    end
    local id = sid_cache[ param ]
    iid_cache [ id ] = base.iid( id )
    return id
end

---@param self mUnit
---@param params table => player, id, x, y, face
---@return unit
function unit:new( params )
    --id支持  @农民   *农   hpea 最终都会转成hpea
    local id = params.id or 'hpea'
    id = sid_cache[ id ] or convert_id( id )
    ---@class unit
    local data = {
        type = 'unit',
        player = params.player,
        id = id,
        _id = iid_cache[ id ]
    }

    local h = CreateUnit(
        data.player.handle,
        data._id,
        params.x or 0,
        params.y or 0,
        params.face or 270
    )
    data.handle = h
    data.hid = cj.GetHandleId(h)

    setmetatable(data, cUnit)

    data:init( )
    
    return data
end

---@private 初始化单位
function cUnit:init()
    local slk = xslk.unit( self.id )
    self.slk = slk
    self.isHero = self.id:byte(1,1) <= 90
    self.isbuilding = slk.isbldg ~= 0
    self.fused      = slk.fused   -- food used 使用的人口
    self.fmade      = slk.fmade   -- food made 提供的人口
    self.goldcost   = slk.goldcost   --建造 金币消耗
    self.lumbercost = slk.lumbercost--建造 木材消耗

    self.Name = cj.GetUnitName( self.handle ) or slk.Name --作为不变名称 与slk用同一key 方便记忆
    self.name = self.Name

    ---@type event[]
    self.events = {}

    unit._h2u[self.hid] = self

    unit:update( '单位-初始化',
        {
            unit = self,
        }
    )

end

---@comment 将非unit模块创建的单位(h)转化为unit对象(o)
---@comment 可以用来将预设单位嵌入unit模块
---@param u handle 单位
---@return unit
function unit:h2o( u )
    local hid = cj.GetHandleId( u )
    if hid == 0 then return end
    if unit._h2u[ hid ] then return unit._h2u[ hid ] end

    local iid = cj.GetUnitTypeId(u)
    ---@class unit
    local data = {
        type = 'unit',
        player = player[ cj.GetPlayerId( cj.GetOwningPlayer( u ) ) + 1 ],
        _id = iid,
        id = base.sid( iid ),
    }
    data.handle = u
    data.hid = hid

    setmetatable(data, cUnit)

    data:init()

    return data
end

---将handleId转化为unit对象
---@param hid int GetHandleId
---@return unit|nil 如果没
function unit:hid2unit( hid )
    if unit._h2u[hid] then
        return unit._h2u[hid]
    end
end

---@ 设置单位XY
---@param x real
---@param y real
function cUnit:setXY( x, y )
    if x then
        self:setX( x )
    end
    if y then
        self:setY( y )
    end
end

---@ 设置单位X坐标
---@param x real
function cUnit:setX( x )
    SetUnitX( self.handle, x )
end

---@ 设置单位Y坐标
---@param y real
function cUnit:setY( y )
    SetUnitY( self.handle, y )
end

---@ 获取单位X坐标
---@return real
function cUnit:getX( )
    return GetUnitX( self.handle )
end

---@ 获取单位Y坐标
---@return real
function cUnit:getY( )
    return GetUnitY( self.handle )
end

--- 删除单位
function cUnit:del()
    unit:update( '单位-销毁数据',
        {
            unit = self,
        }
    )
    self.destroyed = true
    local hid = self.hid
    unit._h2u[ hid ] = nil
    RemoveUnit( self.handle )
    self.abilitys = nil
    self.events = nil
    unit:event_gc('单位-死亡')
    setmetatable(self,nil)
end

---@return player 获取所属玩家对象
function cUnit:getOwner()
    return self.player
end

---@param p player 新的所属玩家
---@param flag bool 是否改变颜色
function cUnit:setOwner(p,flag)
    local b = false
    if flag then
        b = true
    end
    SetUnitOwner(self.handle, p.handle, b)
    self.player = p
end